package club.janna.hello.parser.constants;

import club.janna.hello.frame.DataUnit;
import club.janna.hello.util.DataConvertor;

import java.util.Calendar;
import java.util.Date;

/**
 * 376.1 常量
 * Created by guopanbo on 18/4/11.
 */
public class GDW376D1Statute {


    /**
     * 采集时间间隔
     * 毫秒
     */
    public static final long COLLECT_INTERVAL = 1 * 10 * 1000;
    /**
     * 起始
     */
    public static final byte START = 0x68;
    /**
     * 结束
     */
    public static final byte END = 0x16;

    /**
     * 功能码-链路测试-请求
     */
    public static final byte FUNCTION_REQ_CODE_LINK_TEST = 9;

    /**
     * 功能码-请求1级数据-请求
     */
    public static final byte FUNCTION_REQ_QUERY1 = 11;

    /**
     * 功能码-用户数据-响应
     */
    public static final byte FUNCTION_RES_USER_DATA = 8;

    /**
     * 功能码-链路状态-响应
     */
    public static final byte FUNCTION_RES_CODE_LINK_TEST = 11;

    /**
     * 应用层功能码-确认/否认
     */
    public static final short AFN_CONFIRM = 0x00;

    /**
     * 应用层功能码-链路接口检测
     */
    public static final short AFN_LINK_TEST = 0x02;

    /**
     * 应用层功能码-中继站命令
     */
    public static final short AFN_RELAY = 0x03;

    /**
     * 应用层功能码-请求1类数据
     */
    public static final short AFN_QUERY1 = 0x0c;

    /**
     * 万分位
     */
    private static final float POSITION_WANFEN = 0.000_1f;

    /**
     * 千分位
     */
    private static final float POSITION_QIANFEN = 0.001f;

    /**
     * 百分位
     */
    private static final float POSITION_BAIFEN = 0.01f;

    /**
     * 十分位
     */
    private static final float POSITION_SHIFEN = 0.1f;

    /**
     * 个位
     */
    private static final float POSITION_GE = 1f;

    /**
     * 十位
     */
    private static final float POSITION_SHI = 10f;

    /**
     * 百位
     */
    private static final float POSITION_BAI = 100f;

    /**
     * 千位
     */
    private static final float POSITION_QIAN = 1_000f;

    /**
     * 万位
     */
    private static final float POSITION_WAN = 10_000f;

    /**
     * 十万位
     */
    private static final float POSITION_SHIWAN = 100_000f;


    /**
     * 计算校验
     * @param source
     * @return
     */
    public static int CRC(int[] source) {
        int crc = 0;
        for(int i = 6;i < source.length - 2;i ++) {
            crc += source[i];
        }
        return crc & 0xff;
    }

    /**
     * 根据数据单元生成P
     * @param du
     * @return
     */
    public static short generateP(DataUnit du) {
        if(du == null || du.getDa1() == null)
            return -1;
        if(Integer.parseInt(du.getDa1(), 2) == 0 && du.getDa2() == 0)
            return 0;
        return (short)((du.getDa2() - 1) * 8 + getPositionOf1(du.getDa1()));
    }

    /**
     * 根据pn获取da1
     * @param pn
     * @return
     */
    public static String getDa1ByP(int pn) {
        if(pn == 0)
            return "0";
        return Integer.toBinaryString(0b1 << ((pn & 0b111) == 0 ? 7 : (pn & 0b111) - 1));
    }

    /**
     * 根据pn获取da2
     * @param pn
     * @return
     */
    public static short getDa2ByP(int pn) {
        return (short)((pn & 0b111) == 0 ? pn / 8 : (pn / 8 + 1));
    }

    /**
     * 根据fn获取dt1
     * @param fn
     * @return
     */
    public static String getDt1ByF(int fn) {
        return Integer.toBinaryString(0b1 << ((fn & 0b111) == 0 ? 7 : (fn & 0b111 - 1)));
    }

    /**
     * 根据fn获取dt2
     * @param fn
     * @return
     */
    public static short getDt2ByF(int fn) {
        return (short)((fn & 0b111) == 0 ? (fn / 8 - 1) : fn / 8);
    }

    /**
     * 根据数据单元生成F
     * @param du
     * @return
     */
    public static short generateF(DataUnit du) {
        if(du == null || du.getDt1() == null)
            return -1;
        return (short)((du.getDt2()) * 8 + getPositionOf1(du.getDt1()));
    }

    /**
     * 获取字符串中1的位置（从右到左）
     * @param str
     * @return
     */
    private static byte getPositionOf1(String str) {
        return (byte)(str.length() - str.indexOf('1'));
    }

    /**
     * 生成时间标签tp
     * 附录表A.16 数据格式16
     * @return
     */
    public static int[] generateTp16(int pfc) {
        Calendar cale = Calendar.getInstance();
        int[] dest = new int[6];
        dest[0] = pfc;
        dest[1] = DataConvertor.dec2Bcd(cale.get(Calendar.SECOND));
        dest[2] = DataConvertor.dec2Bcd(cale.get(Calendar.MINUTE));
        dest[3] = DataConvertor.dec2Bcd(cale.get(Calendar.HOUR_OF_DAY));
        dest[4] = DataConvertor.dec2Bcd(cale.get(Calendar.DAY_OF_MONTH));
        dest[5] = 0;
        return dest;
    }

    /**
     * 解析tp
     * 附录表A.16 数据格式16
     * @param b1
     * @param b2
     * @param b3
     * @param b4
     * @param b5
     * @return
     */
    public static Date parseTp16(int b1, int b2, int b3, int b4) {
        Calendar cale = Calendar.getInstance();
        cale.set(Calendar.DAY_OF_MONTH, DataConvertor.bcd2Dec(b4));
        cale.set(Calendar.HOUR_OF_DAY, DataConvertor.bcd2Dec(b3));
        cale.set(Calendar.MINUTE, DataConvertor.bcd2Dec(b2));
        cale.set(Calendar.SECOND, DataConvertor.bcd2Dec(b1));
        return cale.getTime();
    }

    /**
     * 数据格式5
     * @return
     */
    public static float A5(int b1, int b2) {
        float v = (b1 & 0xf) * POSITION_SHIFEN + (b1 >> 4) * POSITION_GE
                + (b2 & 0xf) * POSITION_SHI + ((b2 >> 4) & 0b111) * POSITION_BAI;
        return b2 >> 7 == 0 ? v : 0 - v;
    }

    /**
     * 数据格式7
     * @return
     */
    public static float A7(int b1, int b2) {
        float v = (b1 & 0xf) * POSITION_SHIFEN + (b1 >> 4) * POSITION_GE
                + (b2 & 0xf) * POSITION_SHI + (b2 >> 4) * POSITION_BAI;
        return v;
    }

    /**
     * 数据格式9
     * @return
     */
    public static float A9(int b1, int b2, int b3) {
        float v = (b1 & 0xf) * POSITION_WANFEN + (b1 >> 4) * POSITION_QIANFEN
                + (b2 & 0xf) * POSITION_BAIFEN + (b2 >> 4) * POSITION_SHIFEN
                + (b3 & 0xf) * POSITION_GE + ((b3 >> 4) & 0b111) * POSITION_SHI;
        return b3 >> 7 == 0 ? v : 0 - v;
    }

    /**
     * 数据格式14
     * @return
     */
    public static float A14(int b1, int b2, int b3, int b4, int b5) {
        float v = (b1 & 0xf) * POSITION_WANFEN + (b1 >> 4) * POSITION_QIANFEN
                + (b2 & 0xf) * POSITION_BAIFEN + (b2 >> 4) * POSITION_SHIFEN
                + (b3 & 0xf) * POSITION_GE + (b3 >> 4) * POSITION_SHI
                + (b4 & 0xf) * POSITION_BAI + (b4 >> 4) * POSITION_QIAN
                + (b5 & 0xf) * POSITION_WAN + (b5 >> 4) * POSITION_SHIWAN;
        return v;
    }

    /**
     * 数据格式25
     * @return
     */
    public static float A25(int b1, int b2, int b3) {
        float v = (b1 & 0xf) * POSITION_QIANFEN + (b1 >> 4) * POSITION_BAIFEN
                + (b2 & 0xf) * POSITION_SHIFEN + (b2 >> 4) * POSITION_GE
                + (b3 & 0xf) * POSITION_SHI + ((b3 >> 4) & 0b111) * POSITION_BAI;
        return b3 >> 7 == 0 ? v : 0 - v;
    }
}
